package cn.turboinfo.fuyang.api.domain.mini.usecase.product;

import cn.turboinfo.fuyang.api.domain.common.handler.product.ProductDataFactory;
import cn.turboinfo.fuyang.api.domain.common.service.category.CategoryService;
import cn.turboinfo.fuyang.api.domain.common.service.file.FileAttachmentService;
import cn.turboinfo.fuyang.api.domain.common.service.product.ProductService;
import cn.turboinfo.fuyang.api.domain.common.service.shop.HousekeepingShopService;
import cn.turboinfo.fuyang.api.domain.common.usecase.AbstractUseCase;
import cn.turboinfo.fuyang.api.domain.web.component.file.FileRefTypeConstant;
import cn.turboinfo.fuyang.api.entity.common.pojo.category.Category;
import cn.turboinfo.fuyang.api.entity.common.pojo.file.FileAttachment;
import cn.turboinfo.fuyang.api.entity.common.pojo.product.Product;
import cn.turboinfo.fuyang.api.entity.common.pojo.product.QProduct;
import cn.turboinfo.fuyang.api.entity.common.pojo.shop.HousekeepingShop;
import cn.turboinfo.fuyang.api.entity.mini.fo.product.MiniProduct;
import com.google.common.collect.Lists;
import lombok.*;
import lombok.extern.slf4j.Slf4j;
import net.sunshow.toolkit.core.qbean.api.request.QPage;
import net.sunshow.toolkit.core.qbean.api.request.QRequest;
import net.sunshow.toolkit.core.qbean.api.response.QResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author gadzs
 * @description 产品列表
 * @date 2023/2/13 17:05
 */
@Slf4j
@RequiredArgsConstructor
@Component
public class MiniListProductUserCase extends AbstractUseCase<MiniListProductUserCase.InputData, MiniListProductUserCase.OutputData> {

    private final ProductService productService;
    private final FileAttachmentService fileAttachmentService;
    private final ProductDataFactory productDataFactory;

    private final HousekeepingShopService housekeepingShopService;

    private final CategoryService categoryService;

    @Override
    protected MiniListProductUserCase.OutputData doAction(MiniListProductUserCase.InputData inputData) {
        BigDecimal longitude = inputData.getLongitude();
        BigDecimal latitude = inputData.getLatitude();
        String categoryCode = inputData.getCategoryCode();
        QRequest request = inputData.getRequest();

        // 按地区查询
        if (inputData.areaCode != null) {
            List<Object> shopIdList = housekeepingShopService.findByAreaCode(inputData.areaCode)
                    .stream()
                    .map(HousekeepingShop::getId)
                    .collect(Collectors.toList());
            request.filterIn(QProduct.shopId, shopIdList);
        }
        if (StringUtils.isNotBlank(categoryCode)) {
            List<Object> categoryIdList = categoryService.findByCodeWithChildren(categoryCode)
                    .stream()
                    .map(Category::getId)
                    .collect(Collectors.toList());

            request.filterIn(QProduct.categoryId, categoryIdList);
        }

        QResponse<Product> response = productService.findAll(request, inputData.getRequestPage());

        List<Product> productList = response.getPagedData().stream().toList();
        List<Long> productIds = productList.stream().map(Product::getId).collect(Collectors.toList());

        val fileListMap = fileAttachmentService.findByRefIdInAndRefType(productIds, FileRefTypeConstant.PRODUCT_IMG).stream().collect(Collectors.groupingBy(FileAttachment::getRefId));
        productList.forEach(product -> {
            // 查询附件
            product.setImgList(fileListMap.containsKey(product.getId()) ?
                    fileListMap.get(product.getId()).stream().map(FileAttachment::getId).collect(Collectors.toList()) : Lists.newArrayList());
        });
        productDataFactory.assembleShop(productList);
        //productDataFactory.assembleCompany(productList);

        QResponse<MiniProduct> result = response.map(product -> {
            MiniProduct miniProduct = new MiniProduct();
            miniProduct.setProduct(product);
            return miniProduct;
        });

        if (longitude != null && latitude != null) {
            Map<Long, BigDecimal> productIdDistanceMap = productService.calculateDistance(productIds, longitude, latitude);
            result.getPagedData()
                    .forEach(p -> p.setDistance(productIdDistanceMap.get(p.getProduct().getId())));
        }

        return MiniListProductUserCase.OutputData.builder()
                .qResponse(result)
                .build();
    }

    @Getter
    @Setter
    @Builder
    public static class InputData extends AbstractUseCase.InputData {
        private QRequest request;

        private String categoryCode;

        private Long areaCode;

        private QPage requestPage;

        /**
         * 经度
         */
        private BigDecimal longitude;

        /**
         * 纬度
         */
        private BigDecimal latitude;
    }

    @Getter
    @Setter
    @Builder
    public static class OutputData extends AbstractUseCase.OutputData {
        private QResponse<MiniProduct> qResponse;
    }
}
